// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package runtime

import (
	"runtime/internal/atomic"
	"unsafe"
)

// GOMAXPROCS设置可同时执行的最大CPU数
// 并返回上一个设置。默认为
// runtime的值。努马普。如果n<1，则不会改变当前设置。
// 当调度程序改进时，此调用将消失。
func GOMAXPROCS(n int) int {
	if GOARCH == "wasm" && n > 1 {
		n = 1 // WebAssembly还没有线程，所以只能使用一个CPU。
	}

	lock(&sched.lock)
	ret := int(gomaxprocs)
	unlock(&sched.lock)
	if n <= 0 || n == ret {
		return ret
	}

	stopTheWorldGC("GOMAXPROCS")

	// 新进程将由StartWorld处理
	newprocs = int32(n)

	startTheWorldGC()
	return ret
}

// NumCPU返回当前进程可用的逻辑CPU数。
// 
// 在进程启动时通过查询操作系统
// 检查可用CPU集。
// 进程启动后对操作系统CPU分配的更改未反映出来。
func NumCPU() int {
	return int(ncpu)
}

// numgocall返回当前进程进行的cgo调用数。
func NumCgoCall() int64 {
	var n = int64(atomic.Load64(&ncgocall))
	for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
		n += int64(mp.ncgocall)
	}
	return n
}

// NumGoroutine返回当前存在的goroutine数。
func NumGoroutine() int {
	return int(gcount())
}

// go:linkname debug_modinfo runtime/debug。modinfo 
func debug_modinfo() string {
	return modinfo
}

// mayMoreStackPreempt是一个maymorestack钩子，在每个可能的合作抢占点强制抢占。
// 
// 这对应用于运行时很有价值，它可能对
// 抢占点敏感。要将其应用于
// 运行时和类似运行时的代码中的所有抢占点，在bash或zsh中使用以下命令：
// 
// X=（{gc，asm}flags={runtime/…，reflect，sync}=-d=maymorestack=runtime.maymorestackprempt）GOFLAGS=${X[@]}
// 
// 这必须是非常不完整的，因为它是在堆栈设置之前从函数
// 开始调用的，因为编译器将调用它从任何可拆分的开场白（导致无限
// 递归）。
// 
// 理想情况下，它也应该使用很少的堆栈，因为链接器
// 目前在nosplit堆栈深度检查中没有考虑到这一点。
// 
// go:nosplit 
// 
// 确保可以为所有ABI调用mayMoreStackPreempt。
// 
// go:linkname mayMoreStackPreempt 
func mayMoreStackPreempt() {
	// 不要在g0或gsignal堆栈上执行任何操作。
	g := getg()
	if g == g.m.g0 || g == g.m.gsignal {
		return
	}
	// 强制抢占，除非堆栈已经中毒。
	if g.stackguard0 < stackPoisonMin {
		g.stackguard0 = stackPreempt
	}
}

// mayMoreStackMove是一个maymorestack钩子，在每个可能的点强制堆栈移动。
// 
// 请参阅mayMoreStackPreempt。
// 
// go:nosplit 
// go:linkname mayMoreStackMove 
func mayMoreStackMove() {
	// 不要在g0或gsignal堆栈上执行任何操作。
	g := getg()
	if g == g.m.g0 || g == g.m.gsignal {
		return
	}
	// 强制堆栈移动，除非堆栈已中毒。
	if g.stackguard0 < stackPoisonMin {
		g.stackguard0 = stackForceMove
	}
}
